/*
 * Copyright Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gm.commonlib.module.image.takeimage;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;

import androidx.core.app.ActivityCompat;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;


import com.gm.commonlib.R;
import com.gm.commonlib.views.dialog.CustomDialog;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Utility to request and check System permissions for apps targeting Android M (API >= 23).
 */
public class EasyPermissions {

    private static final String TAG = "EasyPermissions";

    public interface PermissionCallbacks extends
            ActivityCompat.OnRequestPermissionsResultCallback {

        void onPermissionsGranted(int requestCode, List<String> perms);

        void onPermissionsDenied(int requestCode, List<String> perms);

        void onAllPermissionsGranted(int requestCode, Object mRequestParam);
    }

    public static PermissionHelper createPermissionHelper(Activity activity) {
        return new PermissionHelper(activity, activity);
    }

    public static PermissionHelper createPermissionHelper(Fragment fragment) {
        return new PermissionHelper(fragment.getActivity(), fragment);
    }

    /**
     * 如果该对象设置了PermissionCallbacks，则优先调用该回调,否则，
     * 如果对应的Activity或者Fragment实现了PermissionCallbacks 则调用该回调接口，
     * 否则不做任何处理
     */
    public static class PermissionHelper {

        private Object mCaller;
        private Context mContext;
        private PermissionCallbacks callbacks;
        private final ArrayList<String> mPermissionList = new ArrayList<>();
        private int mRequestCode;
        private Object mRequestParam;

        private String mPromptString = "";

        private PermissionHelper(Context context, Object call) {
            mCaller = call;
            mContext = context;
        }

        /**
         * Check if the calling context has a set of permissions.
         *
         * @param perms one ore more permissions, such as {@code android.Manifest.permission.CAMERA}.
         * @return true if all permissions are already granted, false if at least one permission
         * is not yet granted.
         */
        private String[] hasPermissions(List<String> perms) {
            List<String> list = new ArrayList<>();
            for (String perm : perms) {
                boolean hasPerm = (PermissionChecker.checkSelfPermission(mContext, perm) == PermissionChecker.PERMISSION_GRANTED);
                if (!hasPerm) {
                    list.add(perm);
                }
            }
            if (list.isEmpty()) {
                return null;
            }
            return list.toArray(new String[list.size()]);
        }

        private boolean shouldShowRationale(String... perms) {
            boolean shouldShowRationale = false;
            for (String perm : perms) {
                if (mCaller instanceof Activity) {
                    shouldShowRationale = ActivityCompat.shouldShowRequestPermissionRationale((Activity) mCaller, perm);
                } else if (mCaller instanceof Fragment) {
                    shouldShowRationale = ((Fragment) mCaller).shouldShowRequestPermissionRationale(perm);
                } else {//永远不应该被执行
                    shouldShowRationale = false;
                }

                if (shouldShowRationale) {
                    return true;
                }
            }
            return shouldShowRationale;
        }

        public void setPromptString(String promptString) {
            mPromptString = promptString;
        }

        public void setPermissionCallbacks(PermissionCallbacks callbacks) {
            this.callbacks = callbacks;
        }

        public void addCheckPermission(String... permission) {
            Collections.addAll(mPermissionList, permission);
        }

        /**
         * Request a set of permissions, showing rationale if the system requests it.
         *
         * @param rationale    a message explaining why the application needs this set of permissions, will
         *                     be displayed if the user rejects the request the first time.
         * @param requestCode  request code to track this request, must be < 256.
         * @param requestParam Activity or Fragment requesting permissions. Should implement
         *                     {@link ActivityCompat.OnRequestPermissionsResultCallback}
         */
        public void requestPermissions(String rationale,
                                       final int requestCode, Object requestParam,
                                       DialogInterface.OnClickListener cancelClickListener) {
            requestPermissions(rationale,
                    "申请",
                    mContext.getString(R.string.dialog_btn_cancel),
                    requestCode,
                    requestParam,
                    cancelClickListener);
        }

        /**
         * Request a set of permissions, showing rationale if the system requests it.
         *
         * @param rationale      a message explaining why the application needs this set of permissions, will
         *                       be displayed if the user rejects the request the first time.
         * @param positiveButton custom text for positive button
         * @param negativeButton custom text for negative button
         * @param requestCode    request code to track this request, must be < 256.
         */
        public void requestPermissions(String rationale,
                                       String positiveButton,
                                       String negativeButton,
                                       final int requestCode,
                                       Object requestParam,
                                       DialogInterface.OnClickListener cancelClickListener) {
            mRequestCode = requestCode;
            mRequestParam = requestParam;
            checkCallingObjectSuitability();

            if (rationale == null || "".equals(rationale.trim())) {
                rationale = "是否赋予该权限";
            }

            final String[] perms = hasPermissions(mPermissionList);
            if (perms == null || perms.length == 0) {
                runPermissionsGranted(mPermissionList);
                runAllPermissionsGranted(requestCode);
            } else if (shouldShowRationale(perms)) {
                CustomDialog dialog=new CustomDialog(getContext(),false);
                dialog.setMessage(rationale);
                dialog.setTitle("提示");
                dialog.setRightText("确定");
                dialog.setLeftText("取消");
                dialog.setOnLeftListener(cancelClickListener);
                dialog.setOnRightListener(new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        executePermissionsRequest(perms);
                    }
                });
                dialog.show();
           }
            else {
                executePermissionsRequest(perms);
            }
        }

        /**
         * Handle the result of a permission request, should be called from the calling Activity's
         * {@link ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}
         * method.
         * <p>
         * If any permissions were granted or denied, the Activity will receive the appropriate
         * callbacks through {@link PermissionCallbacks} and methods annotated with
         *
         * @param requestCode  requestCode argument to permission result callback.
         * @param permissions  permissions argument to permission result callback.
         * @param grantResults grantResults argument to permission result callback.
         * @throws IllegalArgumentException if the calling Activity does not implement
         *                                  {@link PermissionCallbacks}.
         */
        public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                               int[] grantResults) {
            if (requestCode == mRequestCode) {
                // Make a collection of granted and denied permissions from the request.
                ArrayList<String> granted = new ArrayList<>();
                ArrayList<String> denied = new ArrayList<>();
                for (int i = 0; i < permissions.length; i++) {
                    String perm = permissions[i];
                    if (PermissionChecker.checkSelfPermission(mContext, perm) == PermissionChecker.PERMISSION_GRANTED) {
                        granted.add(perm);
                    } else {
                        denied.add(perm);
                    }
                }

                // Report granted permissions, if any.
                if (!granted.isEmpty()) {
                    // Notify callbacks
                    runPermissionsGranted(granted);
                }

                // Report denied permissions, if any.
                if (!denied.isEmpty()) {
                    runPermissionsDenied(denied);
                }

                // If 100% successful, call annotated methods
                if (!granted.isEmpty() && denied.isEmpty()) {
                    runAllPermissionsGranted(requestCode);
                }
            }
        }

        private void executePermissionsRequest(String[] perms) {
            if (mCaller instanceof Activity) {
                ActivityCompat.requestPermissions((Activity) mCaller, perms, mRequestCode);
            } else if (mCaller instanceof Fragment) {
                ((Fragment) mCaller).requestPermissions(perms, mRequestCode);
            }
        }

        private Context getContext() {
            return mContext;
        }

        private void runPermissionsGranted(List<String> granted) {
            if (callbacks != null) {
                callbacks.onPermissionsGranted(mRequestCode, granted);
            }
        }

        private void runPermissionsDenied(List<String> denied) {
            if (callbacks != null) {
                callbacks.onPermissionsDenied(mRequestCode, denied);
            }
        }

        private void runAllPermissionsGranted(int requestCode) {
            if (callbacks != null) {
                callbacks.onAllPermissionsGranted(requestCode, mRequestParam);
            }
        }

        private void checkCallingObjectSuitability() {
            // Make sure Object is an Activity or Fragment
            if (!((mCaller instanceof Fragment) || (mCaller instanceof Activity))) {
                throw new IllegalArgumentException("Caller must be an Activity or a Fragment.");
            }

            // Make sure Object implements callbacks
            if (callbacks == null && (mCaller instanceof PermissionCallbacks)) {
                callbacks = (PermissionCallbacks) mCaller;
            } else {
            }
        }
    }
}
